﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Text;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    internal class RealTimeDataRecord : BiffRecord
    {
        private FrtHeader frtHeader;
        private uint ichSamePrefix;
        private XLUnicodeStringSegmentedRTD stTopic;
        private RTDOper rtdOper;
        private List<RTDEItem> rgRTDE;

        protected override void ReadContent(BiffReaderContext context, int length)
        {
            var maxPosition = context.BaseStream.Position + length;
            this.frtHeader = new FrtHeader();
            this.frtHeader.Read(context.Reader);
            Contract.Assert(frtHeader._rt == 0x0813);
            this.ichSamePrefix = context.ReadUInt32();
            this.stTopic = new XLUnicodeStringSegmentedRTD();
            this.stTopic.Read(context.Reader);
            this.rtdOper = new RTDOper();
            this.rtdOper.Read(context.Reader);
            this.rgRTDE = new List<RTDEItem>();
            while (context.Reader.BaseStream.Position < maxPosition)
            {
                RTDEItem item = new RTDEItem();
                item.Read(context.Reader);
                this.rgRTDE.Add(item);
            }
        }

        internal override BiffRecordType RecordType
        {
            get { return BiffRecordType.RealTimeData; }
        }

        internal override void WriteContent(BiffWriterWorkbookContext context)
        {
            throw new NotImplementedException();
        }
    }

    internal class RTDEItem
    {
        private ushort rw;
        private ushort col;
        private ushort itab;

        public void Read(BinaryReader reader)
        {
            this.rw = reader.ReadUInt16();
            this.col = reader.ReadUInt16();
            this.itab = reader.ReadUInt16();
        }
    }

    class RTDOperStr
    {
        private uint cchRTDOperStr;
        private XLUnicodeStringNoCch rgchRTDOperStr;

        public void Read(BinaryReader reader)
        {
            this.cchRTDOperStr = reader.ReadUInt32();
            this.rgchRTDOperStr = new XLUnicodeStringNoCch();
            this.rgchRTDOperStr.Read(reader, (int) cchRTDOperStr);
        }
    }
    internal class RTDOper
    {
        private uint grbit;
        private object rtdVt;

        public void Read(BinaryReader reader)
        {
            this.grbit = reader.ReadUInt32();
            switch (grbit)
            {
                case 0x00000001:
                    rtdVt = reader.ReadDouble();
                    break;
                case 0x00000002:
                case 0x00001000:
                    {
                        var RTDOperStr = new RTDOperStr();
                        RTDOperStr.Read(reader);
                        this.rtdVt = RTDOperStr;
                        break;
                    }
                case 0x00000004:
                    this.rtdVt = reader.ReadUInt32() != 0;
                    break;
                case 0x00000010:
                case 0x00000800:
                    rtdVt = reader.ReadInt32();
                    break;
                default:
                    throw new NotSupportedException();
            }
        }
    }

    internal class XLUnicodeStringSegmentedRTD
    {
        private bool fHighByte;
        private string _value;

        public void Read(BinaryReader reader)
        {
            var cch = reader.ReadUInt32();
            this.fHighByte = (reader.ReadByte() & 0x01) != 0;
            if (!this.fHighByte)
            {
                int charCount = reader.ReadByte();
                byte[] bytes = reader.ReadBytes((int) (cch - 1));
                _value = XlEncodings.OneByteEncoding.GetString(bytes);
            }
            else
            {
                int charCount = reader.ReadUInt16();
                byte[] bytes = reader.ReadBytes((int)(cch - 2));
                _value = XlEncodings.TwoByteEncoding.GetString(bytes);
            }
        }
    }
}